﻿namespace jQube.Web.UI.Controls
{
    using System.ComponentModel;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System;
    using System.Globalization;
    using jQube.Resources;
    using System.Text;

    [RequiredScript("jQube.Resources.Controls.UpdatePanel.jquery.updatePanel-1.0.0.js")]
    [ParseChildren(true)]
    [PersistChildren(true)]
    public class UpdatePanel : WebControl, INamingContainer, IScriptHandledControl
    {
        private TriggerCollection triggerCollection;
        private Control contentContainer;
        private ITemplate contentTemplate;

        public UpdatePanel()
            : base(HtmlTextWriterTag.Div)
        {
            this.RenderMode = RenderMode.Block;
        }

        [DefaultValue(RenderMode.Block)]
        public RenderMode RenderMode { get; set; }

        [PersistenceMode(PersistenceMode.InnerProperty)]
        public TriggerCollection Triggers
        {
            get
            {
                if (this.triggerCollection == null)
                {
                    this.triggerCollection = new TriggerCollection(this);
                }

                return this.triggerCollection;
            }
        }

        [Browsable(false)]
        [PersistenceMode(PersistenceMode.InnerProperty)]
        [TemplateInstance(TemplateInstance.Single)]
        public ITemplate Content
        {
            get
            {
                this.EnsureChildControls();
                return this.contentTemplate;
            }
            set
            {
                if (!this.DesignMode)
                {
                    if (this.contentContainer != null)
                    {
                        throw new InvalidOperationException(
                            String.Format(
                                CultureInfo.InvariantCulture,
                                AtlasWeb.UpdatePanel_CannotSetContentTemplate,
                                this.ID));
                    }

                    this.contentTemplate = value;
                    this.EnsureChildControls();
                }
                else
                {
                    this.contentTemplate = value;
                    this.EnsureChildControls();
                }
            }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public Control ContentContainer
        {
            get
            {
                return this.contentContainer;
            }
        }

        internal bool IsNestedOnUpdatePanel
        {
            get
            {
                Control parent = this.Parent;

                while (parent != null || parent is UpdatePanel)
                {
                    parent = parent.Parent;
                }

                return (parent != null) ;
            }
        }

        protected override void CreateChildControls()
        {
            this.contentContainer = new Control();
            this.Controls.Add(this.contentContainer);

            if (this.contentTemplate != null)
                this.contentTemplate.InstantiateIn(this.ContentContainer);

            base.CreateChildControls();
        }

        protected override ControlCollection CreateControlCollection()
        {
            return new UpdatePanelControlCollection(this) as ControlCollection;
        }

        protected override void OnInit(EventArgs e)
        {
            ScriptManager scriptManager = ScriptManager.GetCurrent(base.Page);

            scriptManager.UpdatePanels.Add(this);
            scriptManager.AddRequiredScript(typeof(UpdatePanel));
            scriptManager.AddInitilizationScript(
                    string.Format("$(\"#{0}\").updatePanel({1});",
                        this.ClientID,
                        this.GetInitilizationOptions()));



            if (!this.DesignMode)
            {
                foreach (Trigger trigger in this.Triggers)
                {
                    if (!trigger.CheckValidTrigger(scriptManager))
                    {
                        throw new InvalidOperationException(
                                    string.Format(AtlasWeb.UpdatePanel_TriggerControlIDAsAsyncPostBackTriggerAndPostBackTrigger,
                                    trigger.TriggerControlID));
                    }
                }

                if (scriptManager.IsAsyncPostBack && !this.IsNestedOnUpdatePanel)
                {
                    this.Attributes.Add("parseableControl", "UpdatePanel");
                }
            }

            base.OnInit(e);
        }

        #region Miembros de IScriptHandledControl

        public string GetInitilizationOptions()
        {
            ScriptManager scriptManager = ScriptManager.GetCurrent(this.Page);
            StringBuilder options = new StringBuilder();

            options.AppendFormat(
@"
            renderMode : {0},
            triggers: {1}
",
              (int)this.RenderMode,
              this.GetTriggersClientIDOptionsArray());

            options.Insert(0, " { ");
            options.Append("\t}");

            return options.ToString();
        }

        internal bool IsDesignMode
        {
            get
            {
                return this.DesignMode;
            }
        }

        #endregion

        private string GetTriggersClientIDOptionsArray()
        {
            StringBuilder triggers = new StringBuilder();

            if (this.Triggers.Count == 0)
            {
                triggers.Append("null");
            }
            else
            {
                ScriptManager scriptManager = ScriptManager.GetCurrent(this.Page);

                triggers.Append("[");

                foreach (Trigger trigger in this.Triggers)
                {
                    Control control = scriptManager.IPage.FindControl(trigger.TriggerControlID);

                    if (control == null)
                    {
                        throw new InvalidOperationException(
                            string.Format(AtlasWeb.UpdatePanel_TriggerControlIDInvalid, trigger.TriggerControlID));
                    }

                    triggers.Append("{");

                    triggers.AppendFormat("\"name\":\"{0}\", \"async\":{1}",
                        control.ClientID,
                        (trigger is AsyncPostBackTrigger).ToString().ToLower());

                    triggers.Append("}");
                    if (this.Triggers.IndexOf(trigger) != this.Triggers.Count - 1)
                    {
                        triggers.Append(", ");
                    }
                }

                triggers.Append("]");
            }

            return triggers.ToString();
        }
    }
}
